package orientation;

import java.util.List;

import org.robotjuice.turtleflip.TurtleService;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 * Orientation manager for handling orientation changes
 * @author matias
 * under GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
 */
public class OrientationManager
{
	private static Sensor sensor;
	private static SensorManager sensorManager;
	private static OrientationListener listener;
	
	private static Boolean supported;
	private static boolean running = false;
	
	/** Sides of the phone */
	enum Side {
		UPSIDE_DOWN,
		NOT_UPSIDE_DOWN,
	}
	
	/**
	 * Returns true if manager is listening for orientation changes
	 */
	public static boolean isListening()
	{
		return running;
	}

	/**
	 * Unregisters listeners
	 */
	public static void stopListening()
	{
		running = false;
		try
		{
			if(sensorManager != null && sensorEventListener != null)
				sensorManager.unregisterListener(sensorEventListener);
		}
		catch(Exception e)
		{
			
		}
	}

	/**
	 * Check if sensor is supported
	 * Is this necessary, force quit if not supported, I don't care
	 * @return boolean
	 */
	public static boolean isSupported()
	{
		if(supported == null)
		{
			if (TurtleService.getContext() != null)
			{
				sensorManager = (SensorManager) TurtleService.getContext().getSystemService(Context.SENSOR_SERVICE);
				List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
				supported = new Boolean(sensors.size() > 0);
			} else {
				supported = Boolean.FALSE;
			}
		}
		return supported;
	}

	/**
	 * Unregister previous and register new one
	 * @param orientationListener
	 */
	public static void startListening(OrientationListener orientationListener)
	{
		sensorManager = (SensorManager) TurtleService.getContext().getSystemService(Context.SENSOR_SERVICE);
		List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
		if(sensors.size() > 0)
		{
			sensor = sensors.get(0);
			sensorManager.unregisterListener(sensorEventListener); // Unregister first
			running = sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
			listener = orientationListener;
		}
	}
 
	/**
	 * Listener for orientation changes
	 * TODO for miika - Still in progress. Can't test with Nexus One. What about Spica?
	 * Trigger orientations according to OrientationListener
	 */
	private static SensorEventListener sensorEventListener = new SensorEventListener()
	{
		private Side currentSide = null;
		private Side oldSide = null;
		
		private float pitch;
		private float roll;
		
		public void onAccuracyChanged(Sensor sensor, int accuracy) {}
		
		public void onSensorChanged(SensorEvent event)
		{
			pitch = event.values[1];
			roll = event.values[2];			
			
			//Using +-5 degrees scale with both axis.
			if (pitch > -185 && pitch < -175 && roll > -5 && roll < 5)
			{
				//Phone is now upside down
				currentSide = Side.UPSIDE_DOWN;
			}
			else
			{
				//Phone returns from upside down
				currentSide = Side.NOT_UPSIDE_DOWN;
			}
			
			if (currentSide != null && oldSide != currentSide)
			{
				switch (currentSide) {
					case UPSIDE_DOWN:
						listener.onFlipDown();
						break;
					case NOT_UPSIDE_DOWN:
						listener.onFlipUp();
						break;
				}
			}
			oldSide = currentSide;
			// Stop listening since we need those values just once
			stopListening(); // Ears off
		}
	};

}
